#include "QNBConfig.h"

#include <QApplication>
#include <QDir>
#include <QFile>
#include <QSettings>
#include <QDebug>
#include <QCamera>

#include "QNBConstant.h"

#include "QNBUserInfo.h"


#define CLIENT_NODE "Client"
#define HEART_INTERVAL_NAME "HeartInterval"
#define UPDATE_CONFIG_INTERVAL_NAME "UpdateConfigInterval"
#define DELETE_USER_DATA_DELAY_TIME_NAME "DeleteUserDataDelayTime"
#define SUBMIT_PHOTO_INTERVAL_NAME "SubmitPhotoInterval"
#define SERVER_IP_NAME "ServerIP"
#define CHECK_PHOTO_SERVER_URL_NAME "CheckPhotoServerUrl"
#define CAMERA_DEVICE_NAME "CameraDevice"
#define CHECK_PHOTO_USE_BASE_NAME "CheckPhotoUseBase64"
#define CHECK_PHOTO_SIMILAR_NAME "CheckPhotoSimilar"
#define CHECK_PHOTO_INTERVAL_NAME   "CheckPhotoInterval"

QNBConfig *QNBConfig::gCfg = NULL;

QNBConfig* QNBConfig::getInstance()
{
    if (gCfg == NULL) {
        gCfg = new QNBConfig();
        gCfg->init();
    }

    return gCfg;
}


QNBConfig::QNBConfig()
{
    miHeartInterval = HEART_INTERVAL;
    miUpdateConfigInterval = UPDATE_CONFIG_INTERVAL;
    miDeleteUserDataDelayTime = DELETE_USER_DATA_DELAY_TIME;
    miSubmitPhotoInterval = SUBMIT_PHOTO_INTERVAL;
    miLockscreenJudgeMaxCount = LOCKSCREEN_JUDGE_MAX_COUNT;

    mstrConfigFile = this->getConfigFilePath();
    mstrUserDataDir = USER_DATA_DIR;

    miCheckPhotoSimilar = PHOTO_SIMILAR_VALUE;

    miCheckPhotoInterval = CHECK_PHOTO_INTERVAL;

    miLoopCheckLoginStatusInterval = LOOP_CHECK_LOGIN_STATUS_INTERVAL;

    miCheckPhotoUseBase64 = 0;
    miCameraDeviceIndex = 0;
    mCameraDevicesList.clear();

    mstrServerIP = "127.0.0.1";
    mstrCheckPhotoServerIP = "http://127.0.0.1:8080/web/";
}


QNBConfig::~QNBConfig()
{

}

void QNBConfig::init()
{
    QDir dir(ROOT_DIR);
    if(!dir.exists()) {
        dir.mkdir(ROOT_DIR);
    }

    QFile file(mstrConfigFile);
    if(!file.exists()) {
        saveConfg();
    }

    listCameraDevices();
    loadConfg();
}

void QNBConfig::saveConfg()
{
    QSettings *cfg = new QSettings(mstrConfigFile, QSettings::IniFormat);

    QString strNode = "/";
    strNode += CLIENT_NODE;
    strNode += "/";

    setNodeInt(cfg, strNode+HEART_INTERVAL_NAME, miHeartInterval);
    setNodeInt(cfg, strNode+UPDATE_CONFIG_INTERVAL_NAME, miUpdateConfigInterval);
    setNodeInt(cfg, strNode+DELETE_USER_DATA_DELAY_TIME_NAME, miDeleteUserDataDelayTime);
    setNodeInt(cfg, strNode+SUBMIT_PHOTO_INTERVAL_NAME, miDeleteUserDataDelayTime);
    setNodeInt(cfg, strNode+CHECK_PHOTO_SIMILAR_NAME, miCheckPhotoSimilar);
    setNodeInt(cfg, strNode+CHECK_PHOTO_USE_BASE_NAME, miCheckPhotoUseBase64);
    setNodeInt(cfg, strNode+CHECK_PHOTO_INTERVAL_NAME, miCheckPhotoInterval);
    setNodeInt(cfg, strNode+CAMERA_DEVICE_NAME, miCameraDeviceIndex);
    setNodeString(cfg, strNode+SERVER_IP_NAME, mstrServerIP);
    setNodeString(cfg, strNode+CHECK_PHOTO_SERVER_URL_NAME, mstrCheckPhotoServerIP);


    delete cfg;
    cfg = NULL;
}

void QNBConfig::loadConfg()
{
    QSettings *cfg = new QSettings(mstrConfigFile, QSettings::IniFormat);

    QString strNode = "/";
    strNode += CLIENT_NODE;
    strNode += "/";
    getNodeInt(cfg, strNode+HEART_INTERVAL_NAME, HEART_INTERVAL,
               miHeartInterval, HEART_INTERVAL, HEART_INTERVAL*5);
    getNodeInt(cfg, strNode+UPDATE_CONFIG_INTERVAL_NAME, UPDATE_CONFIG_INTERVAL,
               miUpdateConfigInterval, UPDATE_CONFIG_INTERVAL, UPDATE_CONFIG_INTERVAL*5);
    getNodeInt(cfg, strNode+DELETE_USER_DATA_DELAY_TIME_NAME, DELETE_USER_DATA_DELAY_TIME,
               miDeleteUserDataDelayTime, DELETE_USER_DATA_DELAY_TIME, DELETE_USER_DATA_DELAY_TIME*5);
    getNodeInt(cfg, strNode+CHECK_PHOTO_SIMILAR_NAME, 0,
               miCheckPhotoSimilar, 0, 100);
    getNodeInt(cfg, strNode+CHECK_PHOTO_USE_BASE_NAME, 0,
               miCheckPhotoUseBase64, 0, 1);
    getNodeInt(cfg, strNode+CHECK_PHOTO_INTERVAL_NAME, 0,
               miCheckPhotoInterval, 10, 40);
    getNodeInt(cfg, strNode+CAMERA_DEVICE_NAME, 0, miCameraDeviceIndex, 0, 5);
    getNodeString(cfg, strNode+SERVER_IP_NAME, "127.0.0.1", mstrServerIP);
    getNodeString(cfg, strNode+CHECK_PHOTO_SERVER_URL_NAME, "http://127.0.0.1:8080/web/", mstrCheckPhotoServerIP);



    delete cfg;
    cfg = NULL;
}

void QNBConfig::setNodeInt(QSettings* cfg, const QString strName, int value)
{
    qDebug()<<"set "<<strName<<"="<<value;
    cfg->setValue(strName, QString("%1").arg(value));
}


void QNBConfig::getNodeInt(QSettings *cfg, QString strName, int defaultValue, int &value, int min, int max)
{
    int iValue = cfg->value(strName, defaultValue).toInt();
    if(value != iValue && iValue >= min && iValue <= max) {
        value = iValue;
    }

    qDebug()<<"get "<<strName<<"="<<value<<" ? "<<iValue;
}


void QNBConfig::setNodeString(QSettings *cfg, QString strFieldName, QString &strValue)
{
    cfg->setValue(strFieldName, strValue);

    qDebug()<<"set "<<strFieldName<<"="<<strValue;
}

void QNBConfig::getNodeString(QSettings *cfg, QString strFieldName, QString defaultValue, QString &strValue)
{
    strValue = cfg->value(strFieldName, defaultValue).toString().trimmed();


    qDebug()<<"get "<<strFieldName<<"="<<strValue;
}

QString QNBConfig::getServerHttpController()
{
    QString strUrl = HTTP_POTOCOL + this->mstrServerIP + HTTP_API_CONTROLLER;

    return strUrl;
}

QString QNBConfig::getConfigFilePath()
{
    QString strConfigFilePath = qApp->applicationDirPath() + QDir::separator() + CONFIG_FILE_NAME;

    qDebug()<<"Config path: "<<strConfigFilePath;

    return strConfigFilePath;
}

QString QNBConfig::getCameraDevices(int index)
{
    if (mCameraDevicesList.size() > index && index >= 0) {
        return mCameraDevicesList.at(index);
    }

    if (mCameraDevicesList.size() > 0) {
        return mCameraDevicesList.at(mCameraDevicesList.size() - 1);
    }

    return "";
}

bool QNBConfig::listCameraDevices()
{
    QList<QByteArray> list = QCamera::availableDevices();


    QString strDevicesPath = qApp->applicationDirPath() + QDir::separator() +"CameraDevices.txt";
    QFile f(strDevicesPath);
    if(!f.open(QIODevice::WriteOnly | QIODevice::Text))
    {
        qDebug() << "Open failed." << endl;
        return -1;
    }

    QTextStream txtOutput(&f);

    for (int i=0; i<list.size(); i++) {
        QString strDevice = list.at(i);
        mCameraDevicesList.append(strDevice);

//        qDebug()<<"Camera "<<i<<" : "<<strDevice.replace("\\", "\\\\");
//        qDebug()<<"Camera "<<i<<" : "<<QCamera::deviceDescription(list.at(i));

        txtOutput<<strDevice.replace("\\", "\\\\")<<endl;
    }
    f.close();

    return true;
}
